// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init()

const db = cloud.database();
const _ = db.command
const $ = _.aggregate

const orders = db.collection('orders')

let log;
/**
 * 获取+8时区的日期对象
 * @param {Date} date 日期
 */
function getRealDate(date) {
  if (date.getTimezoneOffset() == 0) {
    return new Date(date.getTime() + (8 * 60 * 60 * 1000))
  }
  return date;
}

/**
 * 获取+8时区的当天0点日期
 */
function toZereDate(date) {
  date = getRealDate(date)
  return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) - (8 * 60 * 60 * 1000));
}
/**
 * 获取参数中小时和分钟的日期
 * @param {Number} hour 小时
 * @param {Number} minute 分钟
 * @param {Date} date 日期对象
 */
function getHourDate(hm, date = new Date()) {
  const [hour, minute] = hm.split(":");
  date = getRealDate(date)
  return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), hour, minute) - (8 * 60 * 60 * 1000));
}
/**
 * 返回的统一格式
 */
function Message(code = 1, msg = '', data = {}) {
  return {
    code,
    msg,
    data
  };
}

// 云函数入口函数
exports.main = async (event) => {
  // log = cloud.logger()
  const wxContext = cloud.getWXContext()
  switch (event.action) {
    case 'bookByDates': {
      return bookByDates(event)
    }
    case 'user': {
      return user(event)
    }
    case 'cancel': {
      return cancel(event)
    }
    case 'list': {
      return list(event)
    }
    case 'boarding': {
      return boarding(event);
    }
  }
  return {
    event,
    openid: wxContext.OPENID,
    appid: wxContext.APPID,
    unionid: wxContext.UNIONID,
  }
}
/**
 * 用户下多个日期的单 
 * @param {Object} event 请求参数
 */
async function bookByDates(event) {
  let {
    rid,
    name,
    dates
  } = event;
  const {
    OPENID
  } = cloud.getWXContext()
  //验证身份(必须)
  let {
    result
  } = await cloud.callFunction({
    name: 'user',
    data: {
      action: "getUser",
      openId: OPENID,
    }
  })
  if (result.length <= 0) {
    return Message(-1, "未登录");
  } else {
    const [u] = result;
    if (u.status == 0) {
      code = -5;
      msg = "帐号已经被锁定"
      return Message(-5, "帐号已经被锁定");
    } else if (!u.name || u.name == "") {
      code = -3;
      msg = "个人资料未填写"
      return Message(-3, "个人资料未填写");
    }
  }
  const [user] = result;

  //验证路线
  const {
    result: {
      data: route
    }
  } = await cloud.callFunction({
    name: 'route',
    data: {
      action: "detail",
      id: rid,
    }
  })
  if (!route._id) {
    return Message(-21, "无效的路线");
  }
  //最大预约天数不能超出7天后
  let maxDate = new Date();
  maxDate.setDate(maxDate.getDate() + 7);
  let bookDates = [];
  let msg = "";
  const flag = dates.some(item => {
    let res = item.split("-");
    if (res.length != 3) {
      msg = "预约时间格式有误"
      return true;
    }
    const [year, mouth, date] = res;
    if (isNaN(year) || isNaN(mouth) || isNaN(date)) {
      msg = "预约时间有误"
      return true;
    }
    let d = new Date(Date.UTC(year, mouth - 1, date) - (8 * 60 * 60 * 1000));
    if (d.getTime() > maxDate.getTime()) {
      msg = "预约时间超出范围"
      return true;
    }
    bookDates.push(d);
  })
  if (flag) {
    return Message(-29, msg);
  }
  //预订的结果数组
  let bookResult = [];
  //循环预约多个日期
  for (let i = 0; i < bookDates.length; i++) {
    let item = bookDates[i];
    let rDate = getRealDate(item);
    if (!route.week.includes(rDate.getDay())) {
      bookResult.push(Message(-30, "该日不在预约范围"));
      continue;
    }
    const count = await getCountOrderByDate(rid, item);
    if (count >= route.approvedNumberber) {
      bookResult.push(Message(-24, "预约已满"));
      continue;
    }
    const uCount = await getOrderByOpenidAndType(OPENID, route.type, item);
    if (uCount > 0) {
      bookResult.push(Message(-25, "当天已预约"));
      continue;
    }
    latestCannelTime = getHourDate(route.latestAppointmentTime, item);
    //最后预约时间前4分钟不许取消
    latestCannelTime = new Date(latestCannelTime.getTime() - 4 * 60 * 1000);
    let ordersRes = await orders.add({
      data: {
        uid: user._id,
        _openid: OPENID,
        createTime: db.serverDate(),
        updateTime: db.serverDate(),
        date: item,
        rid: route._id,
        status: 1, //1正常 2取消 3已上车
        rType: route.type,
        rName: name,
        uName: user.name,
        uPhone: user.phone ? user.phone : user.wxPhone,
        rNumber: route.number,
        rStart: route.stations[0].name,
        rEnd: route.stations[route.stations.length - 1].name,
        latestCannelTime,
      }
    })
    bookResult.push(Message(1, "预约成功", ordersRes));
  }
  return Message(1, "操作成功", bookResult);
}

/**
 * 获取该线路预约的人数
 * @param {string} rid 路线id
 * @param {Date} date 日期
 */
async function getCountOrderByDate(rid, date) {
  const {
    total
  } = await orders.where({
    rid,
    date,
    status: 1,
  }).count();
  return total;
}

/**
 * 获取在日期时的订单数量
 */
async function getOrderByOpenidAndType(openId, rType, date) {
  const {
    total
  } = await orders.where({
    _openid: openId,
    rType,
    date,
    status: 1,
  }).count();
  return total;
}
/**
 * 获取自己的预约记录
 */
async function user(event) {
  const {
    OPENID
  } = cloud.getWXContext()
  const {
    page = 1
  } = event;
  const size = 10;
  const now = new Date();
  const list = await orders.aggregate().sort({
    createTime: -1,
  }).match({
    _openid: OPENID
  }).project({
    _id: 1,
    createTime: 1,
    date: $.dateToString({
      date: '$date',
      format: '%Y-%m-%d',
      timezone: 'Asia/Shanghai'
    }),
    rEnd: 1,
    rStart: 1,
    rEnd: 1,
    rType: 1,
    rNumber: 1,
    status: 1,
    rName: 1,
    isExpired: $.gte([$.dateFromString({
      dateString: now.toISOString()
    }), '$latestCannelTime'])
  }).skip((page - 1) * size).limit(size).end();
  return Message(1, "", list.list)
}
/**
 * 取消预约
 */
async function cancel(event) {
  const {
    OPENID
  } = cloud.getWXContext()
  const {
    id
  } = event;
  const {
    data
  } = await orders.doc(id).get();

  //校验身份
  if (data._openid != OPENID) {
    return Message(-27, "无权限")
  }

  //校验时间
  const now = new Date();
  // console.log(data.latestCannelTime.getTime());
  if (data.latestCannelTime.getTime() < now.getTime()) {
    return Message(-28, "取消预约时间已超时")
  }

  let res = await orders.doc(id).update({
    data: {
      status: 2,
      updateTime: db.serverDate(),
    }
  })


  return Message(1, "", res);
}
/**
 * 司机获取路线的预约记录
 */
async function list(event) {
  const {
    OPENID
  } = cloud.getWXContext()
  let {
    result
  } = await cloud.callFunction({
    name: 'user',
    data: {
      action: "getUser",
      openId: OPENID,
    }
  });
  if(result[0].role != 2){
    return Message(-29,"无权限")
  }
  const {
    rid,
    page = 1
  } = event;
  const size = 50;
  let date = new Date();
  date = getHourDate("23:59", date);
  const list = await orders.aggregate().sort({
    createTime: -1,
  }).match({
    rid,
    status: $.neq(2), //非取消的订单
    date:$.lt(date) //只取小于当天的订单

  }).project({
    _id: 1,
    rName: 1,
    createTime: $.dateToString({
      date: '$createTime',
      format: '%m-%d %H:%M:%S',
      timezone: 'Asia/Shanghai'
    }),
    date: $.dateToString({
      date: '$date',
      format: '%Y-%m-%d',
      timezone: 'Asia/Shanghai'
    }),
    status: 1,
    uName: 1,
    uPhone: 1,
  }).skip((page - 1) * size).limit(size).end();
  return Message(1, "", list.list)
}
/**
 * 乘客上车
 */
async function boarding(event) {
  const {
    id
  } = event;
  const {
    OPENID
  } = cloud.getWXContext()
  const {
    data
  } = await orders.where({
    rid: id,
    _openid:OPENID,
    date: toZereDate(new Date()),
  }).get();
  //判断有无订单
  if (data.length == 0) {
    return Message(-30, "没有预约该班次")
  }

  let order;
  data.some(item => {
    if (item.status != 2) {
      order = item;
      return true;
    }
  })
  //订单都是取消的
  if (!order) {
    return Message(-31, "预约班次已经被取消")
  }
  //已经上车
  if (order.status == 3) {
    return Message(1, "已经上车")
  }
  await orders.doc(order._id).update({
    data: {
      status: 3,
      updateTime: db.serverDate(),
    }
  })
  return Message(1, "扫码上车成功")

}